Handling Events Outside the Main Event Loop
You'll notice that some types of events--for example,keyUp
andmouseUp
--are simply ignored by the main event loop defined in Listing 4-4. Key-up events are ignored because most applications don't need to know that a key was released, only that it was pressed. Similarly, you usually don't need to know when the mouse button was released, because you're more interested in knowing whether (and where) the mouse button was pressed. In certain cases, however, you will be interested in a mouse-up event. For example, if the user presses the mouse button while the cursor is in a window's close box but then moves the cursor outside the close box before releasing the mouse button, you don't want to handle the mouse-down event. (This is another good example of user-centered design: allowing users to change their minds.)It might appear that a problem is lurking, because the main event loop defined in
Listing 4-4 ignores mouse-up events. How, then, can your application determine that the user released the mouse button when the cursor was outside of the close box? The answer is simple: the system software provides a routine,TrackGoAway
, that you call in response to a user click in the close box. TheTrackGoAway
function tracks user actions involving the close box; it returns the Boolean valueTRUE
if the cursor is still inside the close box when the button is released andFALSE
otherwise. Listing 4-5 illustrates how to callTrackGoAway
.Listing 4-5 Tracking mouse events in the close box
PROCEDURE DoGoAwayBox (myWindow: WindowPtr; mouseloc: Point); BEGIN IF TrackGoAway(myWindow, mouseloc) THEN DoCloseWindow(myWindow); END;TheTrackGoAway
function exits only when the mouse button is released. Because it determines internally when that happens, your application doesn't need to.The system software provides routines to handle the three main cases in which you need to track the mouse and determine if the cursor is in a particular location when the button is released. Here are the main routines you'll use:
Mouse-tracking routine Action TrackBox
Track the cursor in a window's zoom box TrackControl
Track the cursor within a control TrackGoAway
Track the cursor in a window's close box For various purposes, you might need to perform similar tracking on an arbitrary rectangle in a window. The function
DoTrackRect
defined in Listing 4-6 shows one way to define such a function.
Listing 4-6 Tracking the cursor in an arbitrary rectangle
- Note
- Venn Diagrammer calls
DoTrackRect
to handle mouse-down events in the tool icons. See Listing 6-9 beginning on page 121.![]()
FUNCTION DoTrackRect (myWindow: WindowPtr; myRect: Rect): Boolean; VAR myIgnore: LongInt; myPoint: Point; BEGIN InvertRect(myRect); {invert the rectangle} REPEAT Delay(kVisualDelay, myIgnore) UNTIL NOT StillDown; {until mouse is released} InvertRect(myRect); GetMouse(myPoint); {get mouse location} DoTrackRect := PtInRect(myPoint, myRect); END;TheDoTrackRect
function inverts the specified rectangle and keeps it inverted until the user releases the mouse button. The Event Manager functionStillDown
looks in your application's event queue for a mouse-up event; if none is found,StillDown
returnsTRUE
; otherwise,StillDown
returnsFALSE
. Note thatDoTrackRect
loops untilStillDown
returnsFALSE
, indicating that the corresponding mouse-up event has been found. The call to theDelay
procedure within the loop is to ensure that the rectangle is inverted for some minimum, user-perceptible amount of time.
CONST kVisualDelay = 6; {wait 6 ticks (one-tenth second)}TheDoTrackRect
function loops untilStillDown
detects the appropriate mouse-up event and then returns the specified rectangle to its original state by inverting it again. Next,DoTrackRect
calls the Event Manager functionGetMouse
to determine the current position of the cursor. If, when the mouse button is released, the cursor is still inside the specified rectangle (as determined by the QuickDraw routinePtInRect
), thenDoTrackRect
returnsTRUE
.As you can see, you sometimes want to call Event Manager routines from outside your main event loop, most often to monitor mouse movements and button states once the user has clicked in some particular part of a window.